﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;

namespace ExceptionManagementStudy
{
    static class TargetInvocationExceptionStudy
    {
        internal static void Test()
        {
            try
            {
                Console.WriteLine("使用 dynamic 调用（期望的版本）");
                dynamic test = Activator.CreateInstance(typeof(TestClassA));
                test.TestMethod();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.GetType() + ":" + ex.Message);
            }

            try
            {
                Console.WriteLine("使用 反射 调用（非期望的版本）");
                object test = Activator.CreateInstance(typeof(TestClassA));
                test.GetType().GetMethod("TestMethod").Invoke(test, new object[0]);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.GetType() + ":" + ex.Message);
            }

            try
            {
                Console.WriteLine("构造方法抛出的异常");
                new TestClassB();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.GetType() + ":" + ex.Message);
            }

            try
            {
                Console.WriteLine("使用 反射 调用（期望的版本）");
                ThrowInnerException();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.GetType() + ":" + ex.Message);
            }
        }

        private static void ThrowInnerException()
        {
            try
            {
                object test = Activator.CreateInstance(typeof(TestClassA));
                test.GetType().GetMethod("TestMethod").Invoke(test, new object[0]);
            }
            catch (TargetInvocationException ex)
            {
                throw ex.InnerException;
            }
        }

        private class TestClassA
        {
            public void TestMethod()
            {
                throw new Exception("我抛出的异常！");
            }
        }

        private class TestClassB
        {
            static TestClassB()
            {
                throw new Exception("我抛出的异常！");
            }
        }
    }
}
